package client;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Locale;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.event.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;

import common.Utilities;

public class StyleChooser extends JPanel implements ChangeListener, ActionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JColorChooser tcc;
	private JComboBox fontBox;
	private JComboBox fontSizeBox;
	private JLabel colorLabel;
	private JLabel emotSelect;
	private JPopupMenu emotMenu;
	private JPopupMenu colorMenu;
	private ChatWindow chatWin;
	private JLabel bold;
	private JLabel italic;
	
	public StyleChooser(Color initColor, ChatWindow win){
		this.chatWin = win;
		tcc = new JColorChooser(initColor);
		tcc.setPreviewPanel(new JPanel());
		tcc.getSelectionModel().addChangeListener(this);
		tcc.setPreviewPanel(null);
		colorLabel = new JLabel();
		colorLabel.setOpaque(true);
		colorLabel.setBackground(initColor);
		colorLabel.setSize(40, 15);
		colorLabel.setPreferredSize(new Dimension(45,20));
		colorLabel.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				colorMenu.show(e.getComponent(),e.getX(),e.getY());
			}
		});
		
		initEmots();
		emotSelect = new JLabel();
		emotSelect.setIcon(new ImageIcon(Utilities.createImage("resource/emote-select.png", "emotion select")));
		emotSelect.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				emotMenu.show(e.getComponent(), e.getX(), e.getY());
			}
		});
		
		JLabel linkLabel = new JLabel();
		linkLabel.setIcon(new ImageIcon(Utilities.locateResource("resource/link.png"),"insert link"));
		linkLabel.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				chatWin.insertHyperLink();
			}
		});
		
		colorMenu = new JPopupMenu();
		colorMenu.add(tcc);
		
		bold = new JLabel("B",JLabel.CENTER);
		bold.setFont(new Font("Serif",Font.BOLD,16));
		changeBorder(bold,StyleConstants.isBold(win.getLocalStyle()));
		bold.setPreferredSize(new Dimension(25,25));
		bold.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				StyleConstants.setBold(chatWin.getLocalStyle(), !StyleConstants.isBold(chatWin.getLocalStyle()));
				changeBorder(bold,StyleConstants.isBold(chatWin.getLocalStyle()));
				chatWin.changeStyle();
			}
		});
		italic = new JLabel("I",JLabel.CENTER);
		italic.setFont(new Font("Serif",Font.ITALIC,16));
		italic.setPreferredSize(new Dimension(25,25));
		italic.setHorizontalTextPosition(JLabel.CENTER);
		changeBorder(italic, StyleConstants.isItalic(win.getLocalStyle()));
		italic.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				StyleConstants.setItalic(chatWin.getLocalStyle(), !StyleConstants.isItalic(chatWin.getLocalStyle()));
				changeBorder(italic,StyleConstants.isItalic(chatWin.getLocalStyle()));
				chatWin.changeStyle();
			}
		});
		initFonts();
		add(fontBox);
		add(fontSizeBox);
		add(bold);
		add(italic);
		add(linkLabel);
		add(colorLabel);
		add(emotSelect);
	}
	
	public void loadStyle(AttributeSet attr){
		if(attr == null) return;
		fontBox.setSelectedItem(StyleConstants.getFontFamily(attr));
		fontSizeBox.setSelectedItem(StyleConstants.getFontSize(attr));
		colorLabel.setForeground(StyleConstants.getForeground(attr));
		changeBorder(bold,StyleConstants.isBold(attr));
		changeBorder(italic,StyleConstants.isItalic(attr));
	}
	
	private void changeBorder(JLabel label, boolean enabled){
		if(enabled)
			label.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		else
			label.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
	}
	
	private void initFonts(){
		String[] allfonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.getDefault());
		if(chatWin.getSupportFonts()!=null){
			ArrayList<String> commonFonts = new ArrayList<String>();
			ArrayList<String> supportFonts = new ArrayList<String>(Arrays.asList(chatWin.getSupportFonts()));
			for(String f : allfonts){
				if(supportFonts.contains(f))
					commonFonts.add(f);
			}
			fontBox = new JComboBox(commonFonts.toArray(new String[commonFonts.size()]));
		} else{
			fontBox = new JComboBox(allfonts);
		}
		fontBox.setRenderer(new FontRenderer());
		fontBox.setMaximumRowCount(10);
		fontBox.setSelectedItem(StyleConstants.getFontFamily(chatWin.getLocalStyle()));
		fontBox.addActionListener(this);
		fontBox.setFont(new Font(fontBox.getSelectedItem().toString(),Font.BOLD,12));
		
		Integer[] fontsizes = {5,6,7,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
		fontSizeBox = new JComboBox(fontsizes);
		fontSizeBox.setMaximumRowCount(10);
		fontSizeBox.setSelectedItem(StyleConstants.getFontSize(chatWin.getLocalStyle()));
		fontSizeBox.addActionListener(this);
	}
	
	private void initEmots(){
		emotMenu = new JPopupMenu();
		try {
			ArrayList<ImageIcon> emots = new ArrayList<ImageIcon>();
			URL resURL = Utilities.locateResource("resource/emotion/");
			if(resURL.getProtocol().equals("file")){
				File emotFolder = new File(resURL.toURI());
				if(emotFolder.isDirectory()){
					File[] emotFiles = emotFolder.listFiles(new FileListFilter("","png"));
					for(File f : emotFiles){
						emots.add(new ImageIcon(f.toURI().toURL(),f.getName().substring(0,f.getName().lastIndexOf("."))));
					}
				}
			} else{
				String jarPath = resURL.getPath().substring(5, resURL.getPath().indexOf("!"));
				try {
					JarFile jar = new JarFile(URLDecoder.decode(jarPath,"utf-8"));
					Enumeration<JarEntry> entries = jar.entries();
					while(entries.hasMoreElements()) {
						String name = entries.nextElement().getName();
						if(name.startsWith("resource/emotion/")&&name.endsWith(".png")){
							emots.add(new ImageIcon(Utilities.locateResource(name), name.substring(name.lastIndexOf("/")+1,name.lastIndexOf("."))));
						}
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
				final JList emotList = new JList(emots.toArray(new ImageIcon[emots.size()]));
				emotList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
				emotList.setCellRenderer(new EmotionRenderer());
				emotList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
				emotList.setVisibleRowCount(12);
				emotList.addMouseListener(new MouseAdapter(){
					public void mouseClicked(MouseEvent e){
						emotMenu.setVisible(false);
						ImageIcon emotFile = (ImageIcon)emotList.getSelectedValue();
						chatWin.insertIcon(emotFile);
					}
				});
				emotMenu.add(emotList);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void stateChanged(ChangeEvent e) {
		colorLabel.setBackground(tcc.getColor());
		colorMenu.setVisible(false);
		StyleConstants.setForeground(chatWin.getLocalStyle(), tcc.getColor());
		chatWin.changeStyle();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == fontBox){
			StyleConstants.setFontFamily(chatWin.getLocalStyle(), fontBox.getSelectedItem().toString());
			fontBox.setFont(new Font(fontBox.getSelectedItem().toString(),Font.BOLD,12));
			chatWin.changeStyle();
		} else if(e.getSource() == fontSizeBox){
			StyleConstants.setFontSize(chatWin.getLocalStyle(), Integer.valueOf(fontSizeBox.getSelectedItem().toString()));
			chatWin.changeStyle();
		}
		
	}
	
	private class FontRenderer extends JLabel implements ListCellRenderer{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		@Override
		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {
			String fontName = (String) value;
			if(!isSelected)
				setFont(new Font(fontName,Font.PLAIN,12));
			else 
				setFont(new Font(fontName,Font.BOLD,14));
			setText(fontName);
			return this;
		}
		
	}
}
